package com.zer0.tga.art;


import java.util.Arrays;

import com.zer0.tga.math.Box;

public class Bitmap {
	
	public int width;
	public int height;
	public int[] pixel;
	
	public Bitmap(int w, int h) {
        this.width = w;
        this.height = h;
        pixel = new int[w * h];
    }
	
	//draws the given bitmap as a whole to the coordinates given.    
	public void draw(Bitmap bitmap, int x0, int y0) {
		draw(bitmap, x0, y0, x0+bitmap.width, y0+bitmap.height);
	}
	
	//draws the given bitmap as a whole to the coordinates given in specified color
	public void draw(Bitmap bitmap, int x0, int y0, int col) {
		draw(bitmap, x0, y0, x0+bitmap.width, y0+bitmap.height,col);
	}

	//draws the given bitmap to the coordinates given.
    public void draw(Bitmap bitmap, int x0, int y0, int x1,int y1) {
        
    	Box box = new Box(x0,y0,x1,y1);
    	/*int x0 = x;
        int x1 = x + bitmap.w;
        int y0 = y;
        int y1 = y + bitmap.h;*/
        
    	if (box.x0 < 0) box.x0 = 0;
        if (box.y0 < 0) box.y0 = 0;
        if (box.x1 > this.width) box.x1 = this.width;
        if (box.y1 > this.height) box.y1 = this.height;
        
        //accessing array as a width*height matrix, we use drawingWidth to compute it (y*drawingWidth + x)
        // the if's above make changes in computing this, so drawingWidth is not always width
        int drawingWidth = (int) (box.x1 - box.x0); 

        // double loop for each pixel of new bitmap
        for (int j = (int) (box.y0); j < box.y1; j++) 
        {
        	// positionInArray is calculated to find the point [ya+x] in array of the matrix representation [x][y]
        	// leftOfNewBitmap is calculated to start the next loop from the new bitmap's left side
            
        	int positionInArray = (int) (j * width + box.x0);
            int leftOfNewBitmap = (int) ((j - y0) * bitmap.width + (box.x0 - x0)); 
            
            //this is made because in the next loop they will be added with current values, so no need to add twice
            positionInArray -= leftOfNewBitmap;
            
            // leftOfNewBitmap + drawingWidth = rightOfNewBitmap actually
            
            for (int i = leftOfNewBitmap; i < leftOfNewBitmap + drawingWidth; i++) 
            {
            	//if there's a pixel to be drawn (there's a color), then draw it.
                int col = bitmap.pixel[i];
                int alpha = (col >> 24) & 0xff;

				if (alpha == 255) {
					pixel[(int) (positionInArray + i)] = col;
				} else {
					pixel[(int) (positionInArray + i)] = blendPixels(pixel[(int) (positionInArray + i)], col);
				}
            }
        }
    }
    
    //draws the given bitmap as a whole to the coordinates given in specified color
    public void draw(Bitmap bitmap, int x0, int y0, int x1,int y1, int col) {
        
    	Box box = new Box(x0,y0,x1,y1);
    	/*int x0 = x;
        int x1 = x + bitmap.w;
        int y0 = y;
        int y1 = y + bitmap.h;*/
        
    	if (box.x0 < 0) box.x0 = 0;
        if (box.y0 < 0) box.y0 = 0;
        if (box.x1 > this.width) box.x1 = this.width;
        if (box.y1 > this.height) box.y1 = this.height;
        
        //accessing array as a width*height matrix, we use drawingWidth to compute it (y*drawingWidth + x)
        // the if's above make changes in computing this, so drawingWidth is not always width
        int drawingWidth = (int) (box.x1 - box.x0); 

        // double loop for each pixel of new bitmap
        for (int j = (int) (box.y0); j < box.y1; j++) 
        {
        	// positionInArray is calculated to find the point [ya+x] in array of the matrix representation [x][y]
        	// leftOfNewBitmap is calculated to start the next loop from the new bitmap's left side
            
        	int positionInArray = (int) (j * width + box.x0);
            int leftOfNewBitmap = (int) ((j - y0) * bitmap.width + (box.x0 - x0)); 
            
            //this is made because in the next loop they will be added with current values, so no need to add twice
            positionInArray -= leftOfNewBitmap;
            
            // leftOfNewBitmap + drawingWidth = rightOfNewBitmap actually
            
            for (int i = leftOfNewBitmap; i < leftOfNewBitmap + drawingWidth; i++) 
            {
                int alpha = (col >> 24) & 0xff;

				if (alpha == 255) {
					pixel[(int) (positionInArray + i)] = col;
				} else {
					pixel[(int) (positionInArray + i)] = blendPixels(pixel[(int) (positionInArray + i)], col);
				}
            }
        }
    }

    public int blendPixels(int backgroundColor, int pixelToBlendColor) {

    	// a color is composed of Hex values alpha|r|g|b
    	
		int alpha_blend = (pixelToBlendColor >> 24) & 0xff;

		int alpha_background = 256 - alpha_blend;

		int backgroundColor_r = backgroundColor & 0xff0000;
		int backgroundColor_g = backgroundColor & 0xff00;
		int backgroundColor_b = backgroundColor & 0xff;

		int pixelToBlend_r = (pixelToBlendColor & 0xff0000);
		int pixelToBlend_g = (pixelToBlendColor & 0xff00);
		int pixelToBlend_b = (pixelToBlendColor & 0xff);

		pixelToBlend_r = ((pixelToBlend_r * alpha_blend + backgroundColor_r * alpha_background) >> 8) & 0xff0000;
		pixelToBlend_g = ((pixelToBlend_g * alpha_blend + backgroundColor_g * alpha_background) >> 8) & 0xff00;
		pixelToBlend_b = ((pixelToBlend_b * alpha_blend + backgroundColor_b * alpha_background) >> 8) & 0xff;

		return 0xff000000 | pixelToBlend_r | pixelToBlend_g | pixelToBlend_b;
	}

    
	public void clearWithColor(int col) {
		// TODO Auto-generated method stub
		Arrays.fill(pixel, col);
		
	}

	

}
